#ifndef __SINGAPOREBUSROUTESVIEW__
#define __SINGAPOREBUSROUTESVIEW__

// [[[ begin generated region: do not modify [Generated Includes]
#include <aknview.h>
// ]]] end generated region [Generated Includes]

#include "CSingaporeBusGenericView.h"
#include "googlepositioning.h"
#include "positionrequest.h"
#include "SingaporeBusStructures.h"
#include "AsyncFileLoader.h"
#include "IteratorControl.h"
#include <aknnavide.h>
#include <akntabgrp.h>
#include <akntabobserver.h>
#include "CSingaporeBusRouteView.hrh"
#include <SingaporeBus.RSG>
#include "How2GoQuery.h"
#include "SingaporeBusAppUi.h"
#include "SingaporeBusDocument.h"


struct CSingaporeBusRouteViewItem : public CBase
	{
	virtual void DrawItem(CSingaporeBusListBoxItemDrawer* aDrawer,
			TInt aItemIndex, const TRect& aActualItemRect,
			TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
			TBool aItemIsSelected) const = 0;
	virtual TBool HandleCommandL( TInt aCommand ) const = 0;
	virtual TBool ListBoxObserver(CEikListBox* aListBox, MEikListBoxObserver::TListBoxEvent aEventType) const = 0; 
	};

struct CSingaporeBusRouteViewItem_LegFrom : public CSingaporeBusRouteViewItem
	{
	const CJourneyPlannerOutput::CItinerary::CLeg* iLeg;
	CSingaporeBusRouteViewItem_LegFrom(const CJourneyPlannerOutput::CItinerary::CLeg* aLeg) : iLeg(aLeg) { }
	void DrawItem(CSingaporeBusListBoxItemDrawer* aDrawer,
			TInt aItemIndex, const TRect& aActualItemRect,
			TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
			TBool aItemIsSelected) const
			{
			CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
			
			if(doc->iOriginStation->iStationType == TStation::ELDNormal)
				doc->iSingaporeBusDrawItemsLD->DrawItineraryLegFromItemL(aDrawer, iLeg, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			else
				doc->iSingaporeBusDrawItemsSG->DrawItineraryLegFromItemL(aDrawer, iLeg, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			
			}
	virtual TBool HandleCommandL( TInt aCommand ) const
		{
		if(iLeg->iService && iLeg->iFromStation)
			return CSingaporeBusGenericHandler::HandleCommandL(iLeg->iService, iLeg->iFromStation, aCommand);
		else if(iLeg->iFromStation)
			return CSingaporeBusGenericHandler::HandleCommandL(iLeg->iFromStation, aCommand);
		else
			return EFalse;
		}
	virtual TBool ListBoxObserver(CEikListBox* aListBox, MEikListBoxObserver::TListBoxEvent aEventType) const 
		{
		return (iLeg->iFromStation) && (CSingaporeBusGenericHandler::ListBoxObserver(iLeg->iFromStation, aListBox, aEventType));
		}
	};
struct CSingaporeBusRouteViewItem_LegTo : public CSingaporeBusRouteViewItem
	{
	const CJourneyPlannerOutput::CItinerary::CLeg* iLeg;
	CSingaporeBusRouteViewItem_LegTo(const CJourneyPlannerOutput::CItinerary::CLeg* aLeg) : iLeg(aLeg) { }
	void DrawItem(CSingaporeBusListBoxItemDrawer* aDrawer,
			TInt aItemIndex, const TRect& aActualItemRect,
			TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
			TBool aItemIsSelected) const
			{

			CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
			
			if(doc->iOriginStation->iStationType == TStation::ELDNormal)
				doc->iSingaporeBusDrawItemsLD->DrawItineraryLegToItemL(aDrawer, iLeg, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			else
				doc->iSingaporeBusDrawItemsSG->DrawItineraryLegToItemL(aDrawer, iLeg, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
				
			
			}
	virtual TBool HandleCommandL( TInt aCommand ) const
		{
		if(iLeg->iService && iLeg->iToStation)
			return CSingaporeBusGenericHandler::HandleCommandL(iLeg->iService, iLeg->iToStation, aCommand);
		else if(iLeg->iToStation)
			return CSingaporeBusGenericHandler::HandleCommandL(iLeg->iToStation, aCommand);
		else
			return EFalse;
		}
	virtual TBool ListBoxObserver(CEikListBox* aListBox, MEikListBoxObserver::TListBoxEvent aEventType) const 
		{
		return (iLeg->iToStation) && (CSingaporeBusGenericHandler::ListBoxObserver(iLeg->iToStation, aListBox, aEventType));
		}
	};

struct CSingaporeBusRouteViewItem_LegWalk : public CSingaporeBusRouteViewItem
	{
	const CJourneyPlannerOutput::CItinerary::CLeg* iLeg;
	CSingaporeBusRouteViewItem_LegWalk(const CJourneyPlannerOutput::CItinerary::CLeg* aLeg) : iLeg(aLeg) { }
	void DrawItem(CSingaporeBusListBoxItemDrawer* aDrawer,
			TInt aItemIndex, const TRect& aActualItemRect,
			TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
			TBool aItemIsSelected) const
			{

			CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
			
			if(doc->iOriginStation->iStationType == TStation::ELDNormal)
				doc->iSingaporeBusDrawItemsLD->DrawItineraryLegWalkItemL(aDrawer, iLeg, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			else
				doc->iSingaporeBusDrawItemsSG->DrawItineraryLegWalkItemL(aDrawer, iLeg, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			
			}
	virtual TBool HandleCommandL( TInt aCommand ) const
		{
		if(iLeg->iService && iLeg->iToStation)
			return CSingaporeBusGenericHandler::HandleCommandL(iLeg->iService, iLeg->iToStation, aCommand);
		else if(iLeg->iToStation)
			return CSingaporeBusGenericHandler::HandleCommandL(iLeg->iToStation, aCommand);
		else
			return EFalse;
		}
	virtual TBool ListBoxObserver(CEikListBox* aListBox, MEikListBoxObserver::TListBoxEvent aEventType) const 
		{
		return (iLeg->iToStation) && (CSingaporeBusGenericHandler::ListBoxObserver(iLeg->iToStation, aListBox, aEventType));
		}
	};

struct CSingaporeBusRouteViewItem_Total : public CSingaporeBusRouteViewItem
	{
	const CJourneyPlannerOutput::CItinerary* iItinerary;
	CSingaporeBusRouteViewItem_Total(const CJourneyPlannerOutput::CItinerary* aItinerary) : iItinerary(aItinerary) { }
	void DrawItem(CSingaporeBusListBoxItemDrawer* aDrawer,
			TInt aItemIndex, const TRect& aActualItemRect,
			TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
			TBool aItemIsSelected) const
			{
			CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
			
			if(doc->iOriginStation->iStationType == TStation::ELDNormal)
				doc->iSingaporeBusDrawItemsLD->DrawItineraryTotalItemL(aDrawer, iItinerary, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			else
				doc->iSingaporeBusDrawItemsSG->DrawItineraryTotalItemL(aDrawer, iItinerary, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			
			}
	virtual TBool HandleCommandL( TInt aCommand ) const
		{
		return EFalse;
		}
	virtual TBool ListBoxObserver(CEikListBox* aListBox, MEikListBoxObserver::TListBoxEvent aEventType) const 
		{
		return EFalse;
		}
	};


class CSingaporeBusRouteView : public CSingaporeBusGenericView<const CSingaporeBusRouteViewItem*, CSingaporeBusRouteView>
	{
	
	RArray<const CSingaporeBusRouteViewItem*> iItems;
	
public:

	TInt iCurrentItinerary;
	
	virtual TBool FilterItem(const CSingaporeBusRouteViewItem* aItem, const TDesC8& aSearchText)
		{ return ETrue; }
	virtual TReal32 OrderItem(const CSingaporeBusRouteViewItem* aItem)
		{ return 0; }
	virtual TBool ListBoxObserver(const CSingaporeBusRouteViewItem* aItem, CEikListBox* aListBox, MEikListBoxObserver::TListBoxEvent aEventType) 
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		return aItem->ListBoxObserver( aListBox, aEventType );
		}
	virtual TBool HandleCommandL( const CSingaporeBusRouteViewItem* aItem, TInt aCommand ) 
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		this->iContainer->iIteratorControl->DrawDeferred();
		return aItem->HandleCommandL( aCommand );
		}
	
	void StoreViewStateL(TDes8& aCustomMessage)
		{
		CSingaporeBusGenericView<const CSingaporeBusRouteViewItem*, CSingaporeBusRouteView>::StoreViewStateL(aCustomMessage);
		StoreCustomMessageParamL(aCustomMessage, _L8("curitin"), _L8("%d"), iCurrentItinerary);
		}
	
	virtual CEikListBox* CreateListBoxL()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		const TInt minHeight = doc->iSingaporeBusDrawItemsSG->PrimaryFont()->FontMaxHeight() + doc->iSingaporeBusDrawItemsSG->SecondaryFont()->FontMaxHeight()*2;
		return ConstructListBoxL(
				new (ELeave) CSingaporeBusListBox,
				minHeight + (ClientRect().Height() % minHeight)/(ClientRect().Height() / minHeight)
				);
		//return ConstructListBoxL(new (ELeave) CAknDoubleStyleListBox);
		}
	virtual void FormatItem(TDes& aBuf, const CSingaporeBusRouteViewItem* aItem)
	{
	}
	void DrawItem(CSingaporeBusListBoxItemDrawer* aDrawer, const CSingaporeBusRouteViewItem* aItem,
			TInt aItemIndex, const TRect& aActualItemRect,
			TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
			TBool aItemIsSelected)
		{
		aItem->DrawItem(aDrawer, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
		}
	
	
	void NotifyJourneyPlannerQueryAnswerL()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		if(iContainer)
			InitializeList();
		}
	
	
	
	void ConstructL()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusGenericView<const CSingaporeBusRouteViewItem*, CSingaporeBusRouteView>::ConstructL( R_SINGAPORE_BUS_ROUTE_VIEW,  R_SINGAPORE_BUS_ROUTE_MARK_MENU, R_SINGAPORE_BUS_STOPS_ICONS, ESingaporeBusRouteViewId );
		}
							
	
protected:
	void DoActivateL(
		const TVwsViewId& aPrevViewId,
		TUid aCustomMessageId,
		const TDesC8& aCustomMessage )
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusGenericView<const CSingaporeBusRouteViewItem*, CSingaporeBusRouteView>::DoActivateL(aPrevViewId, aCustomMessageId, aCustomMessage );
		iCurrentItinerary = 0;
		TPtrC8 field, value, remainder(aCustomMessage);
		while(ParseCustomMessageParamL(field, value, remainder))
			{
			if(field == _L8("curitin"))
				{
				TLex8 lex(value);
				lex.Val(iCurrentItinerary);
				}
			}
		InitializeList();
		RestoreViewStateL(aCustomMessage);
		}
	
	void DoDeactivate()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		this->SetEmptyUnderlyingL();
		for(TInt i = 0 ; i < iItems.Count() ; ++i)
			delete iItems[i];
		iItems.Reset();
		CSingaporeBusGenericView<const CSingaporeBusRouteViewItem*, CSingaporeBusRouteView>::DoDeactivate();
		}
	
	void InitializeList()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		
		if(
				(doc->iOriginStation->iStationType == TStation::ELDNormal && doc->iTflJourneyPlannerQuery->Pending() )
				|| (doc->iHow2GoQuery->Pending() )
			)
			{
			this->SetEmptyUnderlyingL();
			iContainer->iIteratorControl->iListBox->View()->SetListEmptyTextL(_L("requesting..."));
			iContainer->iIteratorControl->iListBox->DrawDeferred();
			}
		else if( doc->iJourneyPlannerOutput && doc->iJourneyPlannerOutput->iItineraries.Count() > 0 )
			{
			if(iCurrentItinerary >= doc->iJourneyPlannerOutput->iItineraries.Count())
				iCurrentItinerary = 0;
			
			for(TInt i = 0 ; i < iItems.Count() ; ++i)
				delete iItems[i];
			iItems.Reset();
			for(TInt i = 0 ; i < doc->iJourneyPlannerOutput->iItineraries[iCurrentItinerary]->iLegs.Count() ; ++i)
				{
				const CJourneyPlannerOutput::CItinerary::CLeg* leg = doc->iJourneyPlannerOutput->iItineraries[iCurrentItinerary]->iLegs[i];
				switch(leg->iMode)
					{
					case CJourneyPlannerOutput::CItinerary::CLeg::BUS:
					case CJourneyPlannerOutput::CItinerary::CLeg::OTHER:
						{
						iItems.AppendL(
								new (ELeave) CSingaporeBusRouteViewItem_LegFrom(leg)
						);
						iItems.AppendL(
								new (ELeave) CSingaporeBusRouteViewItem_LegTo(leg)
						);
						}
						break;
					case CJourneyPlannerOutput::CItinerary::CLeg::WALK:
						iItems.AppendL(
								new (ELeave) CSingaporeBusRouteViewItem_LegWalk(leg)
						);
						break;
					}
				}

			{
			iItems.AppendL(
					new (ELeave) CSingaporeBusRouteViewItem_Total(doc->iJourneyPlannerOutput->iItineraries[iCurrentItinerary])
			);
			}
			
			iUnderlying = 
				new (ELeave) CArrayIterator<const CSingaporeBusRouteViewItem*>(&iItems[0], iItems.Count());
			iContainer->iIteratorControl->SetUnderlying(
					iUnderlying.Get()
					);
			iContainer->iIteratorControl->iListBox->DrawDeferred();
			}
		else if( doc->iJourneyPlannerError != KErrNone || (doc->iJourneyPlannerOutput && doc->iJourneyPlannerOutput->iErrorMessage) )
			{
			TBuf<1024> errorMessage;
			errorMessage.Format(
					_L("Error: (%d, %d)\nMessage: %S"),
					doc->iJourneyPlannerError, doc->iJourneyPlannerStatusCode,
					doc->iJourneyPlannerOutput ? doc->iJourneyPlannerOutput->iErrorMessage : &KNullDesC()
					);
			this->SetEmptyUnderlyingL();
			iContainer->iIteratorControl->iListBox->View()->SetListEmptyTextL(errorMessage);
			iContainer->iIteratorControl->iListBox->DrawDeferred();
			}
		else
			{
			this->SetEmptyUnderlyingL();
			iContainer->iIteratorControl->iListBox->View()->SetListEmptyTextL(_L("Select an origin and a destination station"));
			iContainer->iIteratorControl->iListBox->DrawDeferred();
			}
		this->iContainer->iIteratorControl->iSearchTextChangedFun = NULL; // Deactivate search field
		}
		
	};

#endif // __SINGAPOREBUSROUTESVIEW__
